The string instructions facilitate operations on sequences of bytes or words. None of them take an explicit operand; instead, they all work implicitly on the source and/or destination strings. The current element (byte or word) of the source string is at DS:SI, and the current element of the destination string is at ES:DI. Each instruction works on one element and then automatically adjusts SI and/or DI; if the Direction flag is clear, then the index is incremented, otherwise it is decremented (when working with overlapping strings it is sometimes necessary to work from back to front, but usually you should leave the Direction flag clear and work on strings from front to back).
To work on an entire string at a time, each string instruction can be accompanied by a repeat prefix, either REP or one of REPE and REPNE (or their synonyms REPZ and REPNZ). These cause the instruction to be repeated the number of times in the count register, CX; for REPE and REPNE, the Zero flag is tested at the end of each operation and the loop is stopped if the condition (Equal or Not Equal to zero) fails.
The MOVSB and MOVSW instructions have the following forms:
MOVSB
REP MOVSB
MOVSW
REP MOVSW
The first form copies a single byte from the source string, at address
DS:SI, to the destination string, at address ES:DI, then increments (or
decrements, if the Direction flag is set) both SI and DI. The second form
performs this operation and then decrements CX; if CX is not zero, the operation
is repeated. The effect is equivalent to the following pseudo-C code: while (CX != 0) {
*(ES*16 + DI) = *(DS*16 + SI);
SI++;
DI++;
CX--;
}
(recall that ES*16 + DI is the physical address corresponding to
the segment and offset ES:DI). The remaining two forms move a word at a time,
instead of a single byte; correspondingly, SI and DI are incremented or
decremented by 2 each time through the loop.
The STOSB and STOSW instructions are similar to MOVSB and MOVSW, except the source byte or word comes from AL or AX instead of the memory address in DS:SI. For example, the following is a very fast way to initialize the block of memory from ES:1000h to ES:4FFFh with zeroes:
MOV DI, 1000h ;Starting address
MOV CX, 2000h ;Number of words
MOV AX, 0 ;Word to store at each location
CLD ;Make sure direction is increasing
REP STOSW ;Perform the initialization
Correspondingly, the LODSB and LODSW instructions are
variations on the move instructions where the destination is the
accumulator (instead of the memory address in ES:DI). These are not very useful
operations with the repeat prefix; instead, they are used as part of larger
loops to perform more complex string processing. For example, here is a program
fragment that will convert the NUL-terminated string starting at the address in
DX to be all lower-case (there is a faster way to do the conversion of each
character, using the XLATB instruction, but that is not the point
here): MOV SI, DX ;Initialize source
MOV DI, DX ; and destination indices
MOV AX, DS ;Copy DS (source segment)
MOV ES, AX ; into ES (destination segment)
CLD
NextCh LODSB ;Load next character into AL
CMP AL, 'A'
JB NotUC ;Jump if below 'A'
CMP AL, 'Z'
JA NotUC ; or above 'Z'
ADD AL, 'a' - 'A' ;Convert UC to lc
NotUC STOSB ;Store modified character back
CMP AL, 0
JNE NextCh ;Do next character if not at end of string
None of the preceding string operations have any effect on the status
flags. By contrast, the remaining two string operations are executed
solely for their effect on the status flags, just like the CMP
operation on numbers. The CMPSB and CMPSW operations compare
the current bytes or words of the source and destination strings by subtracting
the destination from the source and recording the properties of the result in
FLAGS. The SCASB and SCASW operations are the variants of this
that use the accumulator (AL or AX) for the source. Each of these may be
preceded by either of the repeat prefixes REPE or REPNE, which
cause the operation to be repeated up to CX times, as long as the condition
holds true after each iteration. Here is the corresponding pseudo-C for REPE
CMPSB: while (CX != 0) {
SetFlags(*(DS*16 + SI) - *(ES*16 + DI));
SI++;
DI++;
CX--;
if (!ZeroFlag) break;
}
A common use of the REPNE SCASB instruction is to find the length
of a NUL-terminated string. Here is an example: MOV DI, DX ;Starting address in DX (assume ES = DS)
MOV AL, 0 ;Byte to search for (NUL)
MOV CX, -1 ;Start count at FFFFh
CLD ;Increment DI after each character
REPNE SCASB ;Scan string for NUL, decrementing CX for each char
MOV AX, -2 ;CX will be -2 for length 0, -3 for length 1, ...
SUB AX, CX ;Length in AX